using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

namespace Woz
{
    internal class PasteAction : Woz.Action
    {
        public PasteAction(bool pPasteInPlace)
        {
            // save the paste in place flag
            this.mPasteInPlace = pPasteInPlace;

            // save whats on the clipboard
            this.mCopiedEntities = Woz.ScreenManager.Instance.CopiedEntities;
        }

        /// <summary>
        /// gets the name of the tool this action prefers
        /// </summary>
        public override string ToolName
        {
            get
            {
                return "Select";
            }
        }

        /// <summary>
        /// gets whether this action can be propagated or not
        /// </summary>
        public override bool Propagatable
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// pastes what is on the clipboard
        /// </summary>
        /// <param name="pScreen">screen to paste to</param>
        protected override void OnExecute(Woz.Screen pScreen)
        {
            // initialize the paste offset
            int pasteOffset = 0;

            if (!this.mPasteInPlace)
            {
                // save the paste offset so we dont have to look it up in the loop
                pasteOffset = Woz.StaticVariables.Instance.PasteOffset *
                    Woz.DynamicVariables.Instance.ConsecutivePaste;

                // also increment the consecutive paste
                Woz.DynamicVariables.Instance.ConsecutivePaste = Woz.DynamicVariables.Instance.ConsecutivePaste + 1;
            }

            // get the selected entities
            this.mSelectedEntities = this.mScreen.SelectedEntities;
            
            // deselect the selected entities
            foreach (Woz.Entity entity in this.mSelectedEntities)
            {
                this.mScreen.DeselectEntity(entity, false);
            }

            // get the pasted entities
            this.mPastedEntities = new Woz.Entity[this.mCopiedEntities.Length];
            for (int i = 0; i < this.mCopiedEntities.Length; i++)
            {
                this.mPastedEntities[i] = this.mCopiedEntities[i].Clone() as Woz.Entity;
            }

            // add the pasted entities
            foreach (Woz.Entity entity in this.mPastedEntities)
            {
                // translate it by paste offset
                entity.Translate(pasteOffset, pasteOffset);

                // add it to the screen
                this.mScreen.AddEntity(entity, false);

                // select it
                this.mScreen.SelectEntity(entity, false);
            }

            // compute the bounding box
            Rectangle boundingBox = Woz.Entity.ComputeBoundingBox(this.mPastedEntities);
            boundingBox = Rectangle.Union(boundingBox, Woz.Entity.ComputeBoundingBox(this.mSelectedEntities));
            boundingBox.Inflate(Woz.InkSpaceConverter.Instance.InkSpaceTenPixels,
                Woz.InkSpaceConverter.Instance.InkSpaceTenPixels);

            // now request the screen to update the bounding box
            Woz.ScreenManager.Instance.RequestSelectedScreenUpdate(pScreen, boundingBox);

            // also request the thumbnail to update
            Woz.ScreenManager.Instance.RequestSelectedScreenThumbnailUpdate(pScreen);
        }

        /// <summary>
        /// unpastes what got pasted
        /// </summary>
        /// <param name="pScreen">screen to unpaste from</param>
        protected override void OnUnExecute(Woz.Screen pScreen)
        {
            // decrement the consecutive paste
            Woz.DynamicVariables.Instance.ConsecutivePaste = Woz.DynamicVariables.Instance.ConsecutivePaste - 1;

            // deselect and remove the pasted entities
            foreach (Woz.Entity entity in this.mPastedEntities)
            {
                this.mScreen.DeselectEntity(entity, false);
                this.mScreen.RemoveEntity(entity, false);
            }

            // select the selected entities
            foreach (Woz.Entity entity in this.mSelectedEntities)
            {
                this.mScreen.SelectEntity(entity, false);
            }

            // compute the bounding box
            Rectangle boundingBox = Woz.Entity.ComputeBoundingBox(this.mPastedEntities);
            boundingBox = Rectangle.Union(boundingBox, Woz.Entity.ComputeBoundingBox(this.mSelectedEntities));
            boundingBox.Inflate(Woz.InkSpaceConverter.Instance.InkSpaceTenPixels, 
                Woz.InkSpaceConverter.Instance.InkSpaceTenPixels);

            // now request the screen to update the bounding box
            Woz.ScreenManager.Instance.RequestSelectedScreenUpdate(pScreen, boundingBox);

            // also request the thumbnail to update
            Woz.ScreenManager.Instance.RequestSelectedScreenThumbnailUpdate(pScreen);
        }

        /// <summary>
        /// the entities that got copied
        /// </summary>
        Woz.Entity[] mCopiedEntities;

        /// <summary>
        /// the entities that got pasted by this paste action
        /// </summary>
        Woz.Entity[] mPastedEntities;

        /// <summary>
        /// the entities that were selected before the paste action took place
        /// </summary>
        Woz.Entity[] mSelectedEntities;

        /// <summary>
        /// whether or not to paste in place
        /// </summary>
        bool mPasteInPlace;
    }
}
